/*
 * $Id:
 *
 * Copyright (C) 2011 Refiner Inc.
 * All right reserved
 *
 *============================================================
 * +rVPN Stack : AppIF (Socket Base Interface)
 *============================================================
 * abstract: This module provides controlling socket for API
 * author  : MURATA
 * history :
 *
 */

#include <errno.h>
#include <pthread.h>
#include "rvs_appif.h"
#include "rvs_socket.h"
#include "rsi_apisock.h"
#include "rsi_tcpipif.h"
#ifdef NO_THREADS
#define USE_THREAD    0
#else
#define USE_THREAD    1
#endif
#include "rrutil.h"

typedef struct _rsi_queue {
    rsi_sock_t* head;
    rsi_sock_t* tail;
#ifndef NO_THREADS
    void* mutex;
#endif
}   rsi_queue_t;

static rsi_sock_t  _rsi_sock_tab[RSI_MAX_SOCK];
static rsi_queue_t _rsi_root;
static int _rsi_init = 0;

char* rsi_apisock_getbuf(int* length, void* param)
{
    /* 本当はここでmbuf関数を呼び出す */
    return rvs_malloc(*length);
}

void rsi_apisock_rlsbuf(char* buf)
{
    /* 本当はここでmbuf関数を呼び出す */
    rvs_free(buf);
}

static inline int rsi_sock_lock(rsi_sock_t* rsock)
{
#ifdef NO_THREADS
    return 0;
#else
    if (rsock->mutex == NULL) {
        rsock->mutex = rr_mutex_init();
    }
    return rr_mutex_lock(rsock->mutex);
#endif
}

static inline void rsi_sock_unlock(rsi_sock_t* rsock)
{
#ifndef NO_THREADS
    rr_mutex_unlock(rsock->mutex);
#endif
}

static inline int rsi_que_lock(void)
{
#ifdef NO_THREADS
    return 0;
#else
    if (_rsi_root.mutex) {
        return rr_mutex_lock(_rsi_root.mutex);
    }
    return -1;
#endif
}

static inline void rsi_que_unlock(void)
{
#ifndef NO_THREADS
    if (_rsi_root.mutex) {
        rr_mutex_unlock(_rsi_root.mutex);
    }
#endif
}

static int rsi_apisock_enq(rsi_sock_t* newp)
{
    if ((newp->next != NULL) || (newp->prev != NULL)) {
        LOGE("%s: new socktab is busy\n", __FUNCTION__);
        return -1;
    }

    newp->prev = _rsi_root.tail;
    newp->next = (rsi_sock_t*)&_rsi_root;

    if (rsi_que_lock()) {
        rsi_sock_unlock(newp);
        return -1;
    }
    if (_rsi_root.tail == (rsi_sock_t*)&_rsi_root) {
        _rsi_root.head = newp;
    } else {
        _rsi_root.tail->next = newp;
    }
    _rsi_root.tail = newp;
    rsi_que_unlock();

    return 0;
}

static int rsi_apisock_deq(rsi_sock_t* delp)
{
    if ((delp->next == NULL) || (delp->prev == NULL)) {
        return -1;
    }

    if (rsi_que_lock()) {
        rsi_sock_unlock(delp);
        return -1;
    }
    delp->prev->next = delp->next;
    delp->next->prev = delp->prev;
    delp->next = delp->prev = NULL;

    rsi_que_unlock();

    return 0;
}

/* 初期化 */
void rsi_apisock_init(void)
{
    int i;

    if (_rsi_init) return;

    _rsi_root.head = _rsi_root.tail = (rsi_sock_t*)&_rsi_root;
#ifndef NO_THREADS
    _rsi_root.mutex = rr_mutex_init();
#endif

    memset (_rsi_sock_tab, 0, sizeof(_rsi_sock_tab));
    for (i=0; i<RSI_MAX_SOCK; i++) {
        _rsi_sock_tab[i].sock = INVALID_SOCKET;
#ifndef NO_THREADS
        _rsi_sock_tab[i].mutex = rr_mutex_init();
#endif
    }

    _rsi_init = 1;
}

/* 終了 */
void rsi_apisock_stop(void)
{
    rsi_sock_t* next = _rsi_root.head;
    void* mutex = _rsi_root.mutex;
    int i;

    if (!_rsi_init) return;

    rsi_que_lock();
    _rsi_init = 0;

    memset (&_rsi_root, 0, sizeof(_rsi_root));
    while (next != (rsi_sock_t*)&_rsi_root) {
        close (next->sock);
        next = next->next;
    }
    for (i=0; i<RSI_MAX_SOCK; i++) {
#ifndef NO_THREADS
        rr_mutex_destroy(_rsi_sock_tab[i].mutex);
#endif
    }
    memset (_rsi_sock_tab, 0, sizeof(_rsi_sock_tab));

    rsi_que_unlock();

#ifndef NO_THREADS
    rr_mutex_destroy(mutex);
#endif
}

/* 新しいソケットの追加 */
int rsi_apisock_new(int sock, struct sockaddr* addr, socklen_t addrlen)
{
    rsi_sock_t* pos;
    int i;

    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return -1;
    }

    pos = rsi_apisock_search(sock);
    if (pos != NULL) return 0;

    pos = _rsi_sock_tab;
    for (i=0; i<RSI_MAX_SOCK; i++, pos++) {
        /* まずはロックする */
        if (rsi_sock_lock(pos)) {
            return -1;
        }
        /* 未使用かどうかのチェック */
        if (pos->sock == INVALID_SOCKET) {
            break;
        }
        /* 使用中なのでロックを解除 */
        rsi_sock_unlock(pos);
    }

    if (i==RSI_MAX_SOCK) return -1;

    /* ソケットの設定(使用中) */
    pos->sock = sock;

    /* 使用中ソケットキューへの追加 */
    rsi_apisock_enq(pos);

    /* ロックを解除 */
    rsi_sock_unlock(pos);

    return 0;
}

/* ソケットの解放 */
void rsi_apisock_free(rsi_sock_t* pos)
{
#ifndef NO_THREADS
    void* mutex;
#endif

    if (pos->next == NULL) return;

    /* ソケット管理情報のロック */
    if (rsi_sock_lock(pos)) {
        return;
    }

    /* 使用中キューから外す */
    rsi_apisock_deq(pos);

    /* フィールドクリア */
#ifndef NO_THREADS
    mutex = pos->mutex;
#endif
    memset (pos, 0, sizeof(rsi_sock_t));
    pos->sock = INVALID_SOCKET;
#ifndef NO_THREADS
    pos->mutex = mutex;
#endif

    /* ロックの解除 */
    rsi_sock_unlock(pos);
}

/* 最初のエントリの取得 */
rsi_sock_t* rsi_apisock_head(void)
{
    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return NULL;
    }

    if (_rsi_root.head != (rsi_sock_t*)&_rsi_root) {
        return _rsi_root.head;
    }
    return NULL;
}

/* 次のエントリ取得 */
rsi_sock_t* rsi_apisock_next(rsi_sock_t* pos)
{
    rsi_sock_t* rsock;

    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return NULL;
    }

    if (pos == NULL) return NULL;

    rsock = pos->next;
    if (rsock != (rsi_sock_t*)&_rsi_root) {
        return rsock;
    }
    return NULL;
}

/* ソケットの取得 */
int rsi_apisock_get(rsi_sock_t*pos)
{
    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return -1;
    }

    if (pos != NULL && pos != (rsi_sock_t*)&_rsi_root) {
        return pos->sock;
    }
    return -1;
}

/* ソケット検索 */
rsi_sock_t* rsi_apisock_search(int sock)
{
    rsi_sock_t* next = _rsi_root.head;

    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return NULL;
    }

    while (next != (rsi_sock_t*)&_rsi_root) {
        if (next->sock == sock) return next;
        next = next->next;
    }

    return NULL;
}

/* 受信メッセージの取得 */
rvs_api_msg_t* rsi_apisock_rmsg(rsi_sock_t* pos)
{
    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return NULL;
    }

    if (pos == NULL || pos == (rsi_sock_t*)&_rsi_root) {
        return NULL;
    }
    if (rsi_sock_lock(pos) < 0) {
        return NULL;
    }
    /* 2011.9.16 すでに解放されているか？ */
    if (pos->sock == INVALID_SOCKET) {
        /* 未使用 */
        rsi_sock_unlock(pos);
        return NULL;
    }

    return &(pos->rmsg);
}

/* 受信メッセージの取得 */
void rsi_apisock_release(rsi_sock_t *pos)
{
    rsi_sock_unlock(pos);
}

/* 受信イベントの処理 */
int rsi_apisock_recv(rsi_sock_t* pos)
{
    rvs_api_msg_t* msg;
    int ret=-1;

    if (!_rsi_init) {
        LOGE("%s: rsi_apisock is not initialized\n", __FUNCTION__);
        return -1;
    }

    /* check */
    if (pos == NULL || pos == (rsi_sock_t*)&_rsi_root) {
        LOGE("%s: pos is invalid\n", __FUNCTION__);
        return -1;
    }
    msg = rsi_apisock_rmsg(pos);
    /* 2011.9.16 すでに解放されているか？ */
    if (msg == NULL) {
        LOGE("%s: cannot get apisock\n", __FUNCTION__);
        return -1;
    }

    /* メッセージ受信 */
    msg = rvs_recv_msg (pos->sock, msg, -1, -1,
                        pos->recvbuf, RSI_RECVBUF_LEN,
                        rsi_apisock_getbuf, NULL);
    rsi_apisock_release(pos);

    if (msg == NULL) {
        if (rvs_errno == RVSA_EOF) {
            return RVSA_EOF;
        }
        LOGE("%s: rvs_recv_msg failed (Err:%d)\n", __FUNCTION__, rvs_errno);
        return -1;
    }

    /* リクエスト受信処理 */
    ret = rsi_tif_request (pos);

    return ret;
}

/* 応答の送信 */
int rsi_apisock_send(rsi_sock_t* pos, rvs_api_send_t* smsg)
{
    int len = -1;
    rvs_api_msg_t* msg = NULL;

    /* check */
    if (pos == NULL || pos == (rsi_sock_t*)&_rsi_root) {
        LOGE("%s: pos is invalid\n", __FUNCTION__);
        goto assnderr;
    }

    msg = rsi_apisock_rmsg(pos);

    if (!msg || !(msg->header)) {
        LOGE("%s: request for smsg(%#x) does not exist\n",
               __FUNCTION__, smsg->header.msgcode);
        goto assnderr;
    }

    /* 受信メッセージとの対応がとれているかの確認 */
    if ( smsg->header.msgcode != RAPI_M_RESP(msg->header->msgcode) ||
         smsg->header.seqno != msg->header->seqno) {
        LOGE("%s: smsg(%x) is not response(%x)\n",
               __FUNCTION__, smsg->header.msgcode, msg->header->msgcode);
        goto assnderr;
    }
    /* 受信メッセージのクリア */
    msg->header->msgcode = 0;

    rsi_apisock_release(pos);

    /* メッセージ送信 */
    if ((len = rvs_send_msg (pos->sock, smsg)) < 0) {
        LOGE("%s: rvs_send_msg failed (Err:%d)\n", __FUNCTION__, rvs_errno);
        goto assnderr;
    }

    return len;

assnderr:
    rsi_apisock_release(pos);
    return -1;
}
